package com.yc.mqtt.handler;

import com.yc.mqtt.handler.message.*;
import com.yc.mqtt.utils.ShareUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.mqtt.MqttFixedHeader;
import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageType;
import io.netty.handler.codec.mqtt.MqttQoS;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

import java.net.InetSocketAddress;

public class EmbedMqttServerHandler extends SimpleChannelInboundHandler<MqttMessage> {


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, MqttMessage mqttMessage) throws Exception {
        MqttFixedHeader mqttFixedHeader = mqttMessage.fixedHeader();
        //遗嘱消息标志
//        MqttConnectVariableHeader mqttConnectVariableHeader = (MqttConnectVariableHeader)mqttMessage.variableHeader();
//        System.out.println(mqttConnectVariableHeader);
//        boolean willFlag = mqttConnectVariableHeader.isWillFlag();
//        if(willFlag){
//            String willMessage = new String(mqttConnectPayload.willMessageInBytes(), CharsetUtil.UTF_8);
//        }


        /**
         *MqttFixedHeader
         bit	7	6	5	4	   3	       2 1	      0
         byte1	Message Type	DUP flag	QoS level	RETAIN
         byte2	            Remaining Length
         */
        MqttMessageType mqttMessageType = mqttFixedHeader.messageType();
        boolean isDup = mqttFixedHeader.isDup();
        boolean isRetain = mqttFixedHeader.isRetain();
        int remainingLength = mqttFixedHeader.remainingLength();
        MqttQoS qoS = mqttFixedHeader.qosLevel();
        System.out.println(mqttFixedHeader);

        System.out.println(mqttFixedHeader.messageType());
        switch (mqttMessageType) {
            case CONNECT:
                ShareUtils.getShareObject(MqttConnectMessageHandler.class).onMessage(channelHandlerContext, mqttMessage);
                break;
            case PUBLISH:
                ShareUtils.getShareObject(MqttPublishMessageHandler.class).onMessage(channelHandlerContext, mqttMessage);
                break;
            case SUBSCRIBE:
                ShareUtils.getShareObject(MqttSubscribeMessageHandler.class).onMessage(channelHandlerContext, mqttMessage);
                break;
            case PINGREQ:
                ShareUtils.getShareObject(MqttPingReqMessageHandler.class).onMessage(channelHandlerContext, mqttMessage);
                break;
            case DISCONNECT:
                break;
            case UNSUBSCRIBE:
                break;
            case PUBACK:
                ShareUtils.getShareObject(MqttPubAckMessageHandler.class).onMessage(channelHandlerContext, mqttMessage);
                break;
            case PUBREC:
                break;
            case PUBREL:
                break;
            case PUBCOMP:
                break;
            default:
                break;
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        System.out.println(socketAddress.getHostName() + ":" + socketAddress.getPort() + " 异常退出~");
        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("【EmbedMqttServerHandler：channelActive】" + ctx.channel().remoteAddress().toString() + "链接成功");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            System.out.println("【userEventTriggered 心跳超时】" + ctx.channel().remoteAddress() + "【channel 关闭】");
            switch (event.state()) {
                case READER_IDLE:
                    ctx.close();
                    break;
                case WRITER_IDLE:
                    ctx.close();
                    break;
                case ALL_IDLE:
                    ctx.close();
                    break;
            }
        }
    }
}
